;8255的C端做输入接 电平开关,A端输出接 数码管
;读入C端的输入,转换为开关编号对应的数码 送入A端传给数码管
;本代码为抢答器
;电平开关模拟抢答按钮 编号0~7 低电平变成高电平的操作视为抢答
;抢答触发后数码管显示编号数字 同时主机响铃
;但存在bug 若多个电平开关同时变位 只会看作最高位的开关抢答成功(此问题暂未找到解决方案)
;此外 用户交互有待加强 

DATA SEGMENT
;-接口区-
IO8255A EQU 288H              ;8255 PA口
IO8255C EQU 28AH              ;8255 PC口
IO8255D EQU 28BH              ;8255 控制端口 
;-数码表- 数码表对应详见文件尾部
LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H 
TS DB 0AH,0DH,'Pres Space to continue,otherwise exit:',0AH,0DH,'$'
DATA ENDS

CODE SEGMENT
ASSUME CS:CODE,DS:DATA 
START:
;初始化设置
      ;数据段初始化
      MOV AX,DATA 
      MOV DS,AX     
      ;向8255控制端口写89H(1000 1001) 
      ;(1)特征位 (00)A方式0 (0)A输出 
      ;(1)C高4位输入 (0)B方式0 (0)B输出 (1)C低4位输入
      ;即C输入 A B输出 工作方式0
      MOV DX,IO8255D
      MOV AL,89H
      OUT DX,AL
      MOV BX,OFFSET LED ; 数码表的入口偏移给BX


;SSS: 从8255的C端读入(电平开关)输入的值到AL 并忽略0
SSS:  MOV DX,IO8255C 
      IN AL,DX 
      ;AL或自身 不改变AL的值 但会根据AL的值改变符号位的值 应该积累
      OR AL,AL          
      JE SSS           ;若AL为0则回到SSS重新读取

;以下代码根据AL值得到高电平开关的编号(0~7)并存入AL
      ;AL中存的是8位电平开关对应的8位二进制数(非0)
      ;对AL右移 若AL为0 说明刚才丢失的位是1 
      ;令CL记录当前右移丢失的对应哪一个开关(0~7)
      MOV CL,0FFH       ;CL赋初值-1
RR:   SHR AL,1          ;AL值逻辑右移一位 
      INC CL            ;CL加一(注意!INC DEC不影响标志位)
      JNC RR            ;AL不是零跳至RR 
      MOV AL,CL         ;将CL记录的值给AL


;显示数字与响铃
      ;将对应的数码送入AL并写到A端 控制数码管显示   
      XLAT              ;将DS:[BX+AL]处的一个字节送入AL
      ;将AL中的数码写入8255的A端 送给数码管
      MOV DX,IO8255A    
      OUT DX,AL 
      ;输出响铃符 制造响铃效果 (字符图案为一个实心圆)
      MOV DL,7          ;响铃符的ASCII为7
      MOV AH,2 
      INT 21H 


;WAI:接收用户键盘输入 若是空格则清空数码管后继续读抢答值
;     若不是空格则直接退出程序
      ;提示用户
WAI:  LEA DX,TS
      MOV AH,9
      INT 21H
      ;接受用户输入一个字符
      MOV AH,1 
      INT 21H 
      CMP AL,20H  ;20H(32) 为空格的ASCII
      JNE EEE     ;若不为空格则结束程序
      ;若是空格 则清空数码管 
      MOV AL,0
      MOV DX,IO8255A
      OUT DX,AL 
      JMP SSS ;回到SSS (继续读入值并显示到数码管)

;EEE结束程序
EEE:  MOV AH,4CH 
      INT 21H  
CODE ENDS
END START


;数码表说明      
;     h g f e d c b a  字符
; 3FH(0 0 1 1 1 1 1 1)  0
; 06H(0 0 0 0 0 1 1 0)  1 
; 5BH(0 1 0 1 1 0 1 1)  2
; 4FH(0 1 0 0 1 1 1 1)  3
; 66H(0 1 1 0 0 1 1 0)  4
; 6DH(0 1 1 0 1 1 0 1)  5
; 7DH(0 1 1 1 1 1 0 1)  6
; 07H(0 0 0 0 0 1 1 1)  7
